enum Priority {
    CRITICAL = 0,       // 紧急事务，一般干扰到正常运作的
    HIGH = 1,           // 高
    NORMAL_HIGH = 2,
    NORMAL = 3,
    NORMAL_LOW = 4,
    LOW = 5,
}

type PriorityQueueBaseImpl<T> = Record<Priority, T[]>;

/**
 * 非二叉堆的优先队列实现
 */
export class PriorityQueue<T> {

    private baseObject: PriorityQueueBaseImpl<T>;

    constructor(baseObject: PriorityQueueBaseImpl<T>) {
        this.baseObject = baseObject;
        this.init();
    }

    init() {
        for (let i = Priority.CRITICAL; i < Priority.LOW; ++i) {
            this.baseObject[i] = [];
        }
    }

    push(item: T, priority: Priority) {
        this.baseObject[priority].push(item);
    }

    pop(): T | undefined {
        for (let i = Priority.CRITICAL; i < Priority.LOW; ++i) {
            if (this.baseObject[i].length > 0) {
                return this.baseObject[i].shift();
            }
        }
        return undefined;
    }

    peek(): T | undefined {
        for (let i = Priority.CRITICAL; i < Priority.LOW; ++i) {
            if (this.baseObject[i].length > 0) {
                return this.baseObject[i][0];
            }
        }
        return undefined;
    }

    size(): number {
        let size = 0;
        for (let i = Priority.CRITICAL; i < Priority.LOW; ++i) {
            size += this.baseObject[i].length;
        }
        return size;
    }

    isEmpty(): boolean {
        return this.size() === 0;
    }

    clear() {
        this.init();
    }

    toArray(): T[] {
        let array = [];
        for (let i = Priority.CRITICAL; i < Priority.LOW; ++i) {
            array = array.concat(this.baseObject[i]);
        }
        return array;
    }

    [Symbol.toStringTag]() {
        return 'PriorityQueue';
    }

    static create<T>() {
        const obj = {} as PriorityQueueBaseImpl<T>;
        return new PriorityQueue(obj);
    }
}